#include "../../include/device/dtuDevice.h"


/**
 * dtu设备负责收发RTCM数据，转发设备基站的控制数据，
 * 此模块内需要两个部分，一个数据接收部分，一个是数据发送部分，每次在接收到数据后需要立刻发送要发送的数据
 * 收发的数据全部放在消息队列内实现
 * */ 
C_dtuDevice::C_dtuDevice(const char *_path, int _speed)
{
    m_recvBuf = NULL;
    m_serial = NULL;
    spdlog::info("C_dtuDevice init {}, {}", _path, _speed);
    m_serial = NULL;
    switch (_speed)  {
    case 115200:
        m_serial = new SerialDriver(_path, BPS115200); // 串口驱动对象，包含了对串口的初始化
        break;
    default:
        spdlog::error("error! SerialDriver band input wrong");
        break;
    }
    m_recvBuf = (uint8_t*)malloc(512*(sizeof(uint8_t)));
}   

C_dtuDevice::~C_dtuDevice()
{
    delete m_serial;
    m_serial = NULL;
    delete m_recvBuf;
    m_recvBuf = NULL;
}



int32_t recvbufLem = 0;
uint8_t recv_buf_dtu[512];
std::vector<uint8_t> cache_buffer;
int32_t C_dtuDevice::getUsartData(std::vector<uint8_t> &usratBuf) // 读取串口数据接口
{
    std::vector<uint8_t> data_buffer;
    int32_t read_result = m_serial->ReadBytes(data_buffer, 0, 100);
    //printf("read_result:%d\n", read_result);
    if(read_result == RECV_DONE){
        cache_buffer.insert(cache_buffer.end(), data_buffer.begin(), data_buffer.end());
    }
    if(cache_buffer.size()>0){
        uint8_t* pos = cache_buffer.data();
        if(cache_buffer[0] == 0x64){ // 寻找包头
            size_t rtcmLen = cache_buffer[1];
            if(cache_buffer.size() >= rtcmLen){
                if(cache_buffer[rtcmLen-2]==0x0d && cache_buffer[rtcmLen-1]==0x0a){ // 寻找包尾
                    usratBuf =  cache_buffer; //(usratBuf.end(), cache_buffer.begin(), cache_buffer.end()); // 转存数据到串口接收内存中，传递给后面的解析部分
                    printf("ttyUSB0 recv len :%ld\n", usratBuf.size());
                    //uint8_t* pos = cache_buffer.data();
                    // for (int i = 0; i < cache_buffer.size(); i++)
                    //     printf("%x ",*pos++);
                    // printf("\n");
                    // 删包
                    std::vector<uint8_t> remaining_buffer; // 处理储存数据后剩余的数据
                    cache_buffer = remaining_buffer;
                    //remaining_buffer.insert(remaining_buffer.end(), cache_buffer.begin()+rtcmLen);
                    return RECV_DONE;
                }
            }
        }
    }
    // // 串口数据读取
    // std::vector<uint8_t> data_buffer;
    // int32_t read_result = m_serial->ReadBytes(data_buffer, 0, 100);
    // if(read_result == RECV_DONE){
    //     cache_buffer.insert(cache_buffer.end(), data_buffer.begin(), data_buffer.end());
    //     // first element
    //     uint8_t* pos = data_buffer.data();
    //     // prints the vector
    //     printf("ttyUSB0:\n");
    //     for (int i = 0; i < data_buffer.size(); i++)
    //         printf("%x ",*pos++);
    //     printf("\n");
    // }
    return REV_NULL;
}

//ADU除去校验码的字节数
//校验码
uint16_t C_dtuDevice::getCRC16(uint8_t *ptr, uint16_t length)
{
    uint8_t i;
    uint16_t crc = 0xFFFF;
    if(length == 0)
        length = 1;
    while(length--) {
        crc ^= *ptr;
        for(i = 0; i < 8; i++){
            if(crc & 1){
                crc >>= 1;
                crc ^= 0xA001;
            } else
                crc >>= 1;
        }
        ptr++;
    }
    return crc;
}

//ADU除去校验码的字节数
//校验码
uint16_t C_dtuDevice::getCRC16(std::vector<uint8_t> &usratBuf,  uint16_t length)
{
    uint8_t i;
    uint16_t crc = 0xFFFF;
    uint8_t* ptr = usratBuf.data();
    //printf("crc length:%d \n", length);
    if(length == 0)
        length = 1;
    while(length--) {
        crc ^= *ptr;
        for(i = 0; i < 8; i++){
            if(crc & 1){
                crc >>= 1;
                crc ^= 0xA001;
            } else
                crc >>= 1;
        }
        *ptr++;
    }
    return crc;
}

void C_dtuDevice::getRTCMbuf(RTCM_RECV *p_rtcmRecvBuf, uint32_t bufLen)
{
    uint32_t tempLenData = 0;
    for(uint32_t i=0; i<bufLen; i++){ // 循环rtcm数据包总个数次
        for(uint32_t j=0; j<p_rtcmRecvBuf[i].rtcmLen; j++){ // 循环每个包的内容
            m_RtcmData.rtcmData[(j+tempLenData)] = p_rtcmRecvBuf[i].rtcmData[j];
        }
        tempLenData = tempLenData + p_rtcmRecvBuf[i].rtcmLen;
    }
    m_RtcmData.rtcmLen = tempLenData;
    printf("rtcmLen:%d \r\n ",tempLenData);
    // for(int i=0; i<m_RtcmData.rtcmLen; i++){
    //     printf("%c ",m_RtcmData.rtcmData[i]);
    // }
    // printf("\r\n");
}

void C_dtuDevice::getUserProtocolData(uint8_t *p_recvBuf, uint32_t rtcmBufLen)
{
    uint32_t tempDataLocat = 0;// 私有协议位置
    tempDataLocat = 5 + rtcmBufLen; // 数据头+数据总长度+rtcm数据包个数+rtcm序号+rtcm数据长度+rtcm数据
    m_userProtocolData.bufLen = p_recvBuf[tempDataLocat];
    // printf("m_userProtocolData.bufLen: %d\r\n", m_userProtocolData.bufLen);
    // for(uint32_t i=0; i<m_userProtocolData.bufLen; i++){
    //     m_userProtocolData.userDataBuf[i] = p_recvBuf[i+tempDataLocat+1];
    //     printf("%c ", m_userProtocolData.userDataBuf[i]);
    // }
    // printf("\r\n");
}


// 解析串口数据
int32_t C_dtuDevice::parsingSerialData(std::vector<uint8_t> &usratBuf)
{
    // 通过状态机接收数据内容并解析
    // 协议数据内容
    /**
     * 1. 数据包头 0x64
     * 2. 储存整个数据包的长度
     * 3. rtcm数据的总个数
     * 4. rtcm数据包的序号
     * 5. rtcm数据包的长度
     * 6. rtcm数据包的内容
     * 7. 其他数据协议内容的长度
     * 8. 其他数据协议的内容
     * 9. 整包数据的crc校验位高位
     * 10. 低位
     * 11. 数据结束帧尾高位
     * 12. 数据结束帧尾低位
    */
    uint32_t baseStationBufLen = 0; // 储存整个数据包的长度数据
    uint32_t rtcmBufTotalNumber = 0; // rtcm数据的总个数  
    uint32_t rtcmNumber = 0; // rtcm数据包序号
    uint32_t rtcmBufLen = 0; // 接收到的rtcm数据长度
    uint16_t crcData = 0;
    
    if(usratBuf[0] == BASE_STATION_PROTOCOL_HEADER){
        //printf("C_dtuDevice::parsingSerialData recvLen:%d\r\n", recvLen);
        // for(uint32_t i=0; i<recvLen; i++){

        // }
        baseStationBufLen = usratBuf[1]; // 2、储存整个数据包的长度数据
        crcData = getCRC16(usratBuf, baseStationBufLen-4);// 计算校验位
        if((uint8_t)crcData == usratBuf[baseStationBufLen-4] && crcData>>8 == usratBuf[baseStationBufLen-3]){
            // CRC校验正常
        }
        else {
            printf("CRC wrong!\r\n");
            return PARSING_ERROR;
        }
        rtcmBufTotalNumber = usratBuf[2]; // 3、储存rtcm数据包的总个数  
        rtcmNumber = usratBuf[3]; // 4、储存rtcm数据包的序号 
        rtcmBufLen = usratBuf[4]; // 5、储存rtcm数据长度

        /* 把RTCM数据存放在结构体数组内*/
        m_rtcmRecvBuf[rtcmNumber].rtcmNumber = rtcmNumber;
        m_rtcmRecvBuf[rtcmNumber].rtcmLen = rtcmBufLen;
        for(int i=0; i<rtcmBufLen; i++){
            m_rtcmRecvBuf[rtcmNumber].rtcmData[i] = usratBuf[i+5];
        }

        /* 检测到是RTCM数据包的最后一包数据后，把RTCM数据从结构体数组内取出，并转换成一个完整的buf*/
        if((rtcmNumber+1) == rtcmBufTotalNumber){ // 如果是RTCM部分的最后一帧数据
            getRTCMbuf(m_rtcmRecvBuf, rtcmBufTotalNumber); // 计算获取到RTCM数据
            return PARSING_RTCM;
        }

        /* 获取私有协议数据 */
        //getUserProtocolData(p_recvBuf, rtcmBufLen);
    }
    else{
        return PARSING_NULL;
    }
    return PARSING_NULL;
}
